home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / SAS-C / sc655pch / guiprof / sprofutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-26  |  5.0 KB  |  218 lines

  1. /*-------------------------------------------------------------------*/
  2. /* Copyright (c) 1992-1995 SAS Institute Inc., Cary NC               */
  3. /*                                                                   */
  4. /* SUPPORT:    walker - Doug Walker                                  */
  5. /* SCRIPT:     sprof                                                 */
  6. /*-------------------------------------------------------------------*/
  7. /* CUT HERE */
  8. #include <exec/types.h>
  9. #include <exec/memory.h>
  10. #include <time.h>
  11. #include <limits.h>
  12. #include <proto/exec.h>
  13. #include <proto/timer.h>
  14. #include <proto/dos.h>
  15. #include <string.h>
  16. #include <dos.h>
  17.  
  18. #include "sprofpriv.h"
  19.  
  20. #include "constructor.h"
  21.  
  22. #define TimerBase MyTimerBase
  23.  
  24. static struct Library *TimerBase;
  25. static struct MsgPort *SprofPort;
  26. static struct timerequest TimerIO;
  27. static struct EClockVal baseline;
  28. static long E_Freq;
  29. static struct MsgPort *replyport;
  30. static struct Task *process;
  31. static int nummsgout;
  32. static struct EClockVal t0;
  33. static unsigned long overhead;
  34.  
  35.  
  36. static int SendMsg(ULONG clkval, char *id, ULONG flags);
  37. static long TimeStamp(void);
  38. static void TimeRestart(void);
  39.  
  40. /* This is an autotermination function that will run when the program exits. */
  41. /* it cleans up the externs that the profiling code uses.                    */
  42. PROFILE_DESTRUCTOR(Sprof)
  43. {
  44.    SPM msg;
  45.    static int skipme;
  46.    FUNCENTRY
  47.  
  48.    if(skipme) return;
  49.  
  50.    skipme = 1;  // Already called, skip it
  51.  
  52.    if(TimerBase)
  53.    {
  54.       CloseDevice((struct IORequest *)&TimerIO);
  55.       TimerBase = NULL;
  56.    }
  57.  
  58.    if(SprofPort && replyport)
  59.       SendMsg(0, 0, SPROF_TERM);
  60.  
  61.    SprofPort = NULL;
  62.  
  63.    if(replyport)
  64.    {
  65.       while(nummsgout > 0)
  66.       {
  67.          while(!(msg=(SPM)GetMsg(replyport)))
  68.             WaitPort(replyport);
  69.          nummsgout--;
  70.          //BUG(("Freed msg 0x%08lx, new nummsgout=%d\n", msg, nummsgout));
  71.          FreeMem(msg, SIZSPM);
  72.       }
  73.       DeletePort(replyport);
  74.       replyport = NULL;
  75.    }
  76. }
  77.  
  78. /* This is an autoinitialization function that runs before the program starts. */
  79. /* It checks to see if we will be profiling this time around and, if so, sets  */
  80. /* up the global variables that will be required.                              */
  81. PROFILE_CONSTRUCTOR(Sprof)
  82. {
  83.    SPM msg;
  84.    FUNCENTRY
  85.  
  86.    if(!(SprofPort = FindPort(SPROFPORT)))
  87.       return 0;
  88.  
  89.    memset(&TimerIO, 0, sizeof(TimerIO));
  90.  
  91.    if(OpenDevice(TIMERNAME, UNIT_ECLOCK, (struct IORequest *)&TimerIO, 37L))
  92.       return(0);
  93.  
  94.    TimerBase = (struct Library *)TimerIO.tr_node.io_Device;
  95.  
  96.    if(!(replyport = CreatePort(0L, 0L)))
  97.    {
  98.       PROFILE_DESTRUCTOR_NAME(Sprof)();  // Does the necessary cleanup
  99.       return -1;
  100.    }
  101.  
  102.    process = FindTask(NULL);
  103.  
  104.    Forbid();
  105.    if(!(SprofPort = FindPort(SPROFPORT)))
  106.    {
  107.       Permit();
  108.       PROFILE_DESTRUCTOR_NAME(Sprof)();
  109.       return 0;  // OK to run with no profiler
  110.    }
  111.  
  112.    SendMsg(0, 0, SPROF_INIT);  // "Here we are!"
  113.  
  114.    Permit();
  115.  
  116.    while(!(msg = (SPM)GetMsg(replyport))) WaitPort(replyport);
  117.  
  118.    PutMsg(replyport, (struct Message *)msg);  // So we can reuse it later
  119.  
  120.    if(msg->flags == SPROF_DENIED || msg->flags == SPROF_TERM) // He doesn't want us
  121.    {
  122.       SprofPort = NULL;  // Make sure we don't try to contact profiler
  123.       PROFILE_DESTRUCTOR_NAME(Sprof)();
  124.       return 0;
  125.    }
  126.  
  127.    /* This needs to go towards the end so the profiler startup */
  128.    /* overhead doesn't count                                   */
  129.    E_Freq = ReadEClock(&baseline) / 1000;
  130.  
  131.    return 0;
  132. }
  133.  
  134.  
  135. static long TimeStamp(void)
  136. {
  137.    ReadEClock(&t0);
  138.  
  139.    /* For now, only use low four bytes. */
  140.    return (long)(t0.ev_lo - baseline.ev_lo - overhead)/E_Freq;
  141. }
  142.  
  143. static void TimeRestart(void)
  144. {
  145.    struct EClockVal t;
  146.  
  147.    ReadEClock(&t);
  148.  
  149.    overhead += (t.ev_lo - t0.ev_lo);
  150. }
  151.  
  152. void __asm _PROLOG(register __a0 char *id)
  153. {
  154.    long t1;
  155.    if(!SprofPort) return;
  156.    t1 = TimeStamp();
  157.    if(!SendMsg(t1, id, SPROF_ENTRY))
  158.       TimeRestart();
  159. }
  160.  
  161. void __asm _EPILOG(register __a0 char *id)
  162. {
  163.    long ts;
  164.    if(!SprofPort) return;
  165.    ts = TimeStamp();
  166.    if(!SendMsg(ts, id, SPROF_EXIT))
  167.       TimeRestart();
  168. }
  169.  
  170. static int SendMsg(ULONG clkval, char *id, ULONG flags)
  171. {
  172.    SPM msg;
  173.  
  174.    if(!(msg = (SPM)GetMsg(replyport)))
  175.    {
  176.       if(!(msg = (SPM)AllocMem(SIZSPM, MEMF_CLEAR)))
  177.       {
  178.          PROFILE_DESTRUCTOR_NAME(Sprof)();
  179.          return -1;
  180.       }
  181.       msg->m.mn_ReplyPort = replyport;
  182.       msg->process = (ULONG)process;
  183.       nummsgout++;
  184.       //BUG(("New msg = 0x%08lx\n", msg));
  185.    }
  186.    else
  187.    {
  188.       if(flags != SPROF_TERM && msg->flags == SPROF_TERM)
  189.       {
  190.          PutMsg(replyport, (struct Message *)msg);  // So it gets freed
  191.          PROFILE_DESTRUCTOR_NAME(Sprof)();
  192.          return -1;
  193.       }
  194.    }
  195.  
  196.    msg->clk = clkval;
  197.    msg->id = id;
  198.    msg->a7 = getreg(REG_A7);
  199.    msg->flags = flags;
  200.    PutMsg(SprofPort, (struct Message *)msg);
  201.    WaitPort(replyport);
  202.    return 0;
  203. }
  204. #if DODEBUG
  205. void bug(char *fmt, ...)
  206. {
  207.    va_list arg;
  208.    char buf[512];
  209.  
  210.    va_start(arg,fmt);
  211.    vsprintf(buf, fmt, arg);
  212.    va_end(arg);
  213.  
  214.    Write(Output(), buf, strlen(buf));
  215. }
  216. #endif
  217.  
  218.